package com.cskaoyan.javase.oop1._2reference;
/**
 * 重新来认识一个引用数据类型
 * 我们第一次认识和了解引用数据类型是在数组这一章节，我们通过JVM内存模型图和数组的初始化过程，知道：
 *
 * 一个(局部变量)引用数据类型变量，分为两个部分：
 *      1.在栈上创建引用，它是一个局部变量。
 *      2.在堆上开辟空间，创建对象。
 * 栈上的引用通过存储堆上对象的地址和对象产生联系。
 * 对象是引用数据类型的实质，但我们只能通过栈上引用间接访问堆上对象。
 *
 * 数据类型: 表示的是一组数据的集合，和基于该数据集合的一组合法操作。
 * 数据类型 = 数据 + 操作
 *
 * 在上一节类的定义中，类中的成员包括：
 * 成员变量
 * 成员方法
 *
 * 成员变量本质上就是数据，成员方法本质上就是操作，那么假设做以下类比：
 * 数据的集合： 类中成员变量的集合
 * 操作的集合： 类中成员方法的集合
 *
 * 于是，就可以做出以下总结：
 *      1.一个类的定义，实际上就是定义了一种全新的数据类型，一种自定义的数据类型。
 *      2.这种完全不同于基本数据类型的数据类型，我们称之为"引用数据类型"。
 *      注意: 在Java中引用数据类型不仅仅包含类,还有一些其它的,比如注解,接口等
 *
 * 引用数据类型的不同点(重点,核心点)
 * 但是类这种引用数据类型，并不是内置数据类型，而是我们自定义的数据类型。
 * 现在我们要根据一个类来创建它的对象，要让JVM帮助我们开辟空间创建引用和对象，JVM怎么知道到底要创建什么呢？难道它未卜先知吗？
 * 所以很明显,JVM在对类这样的引用数据类型做操作之前,必然需要一个步骤: 了解,认识这个类型
 * 在Java中，把JVM"认识,了解"某个类型的过程，称之为类加载(class load)。
 * 关于类加载,后续课程中会详细学习它的流程,今天暂时不讲.
 * 但是我们可以先讲一讲类加载的特点:
 *      1.类加载是通过把某个类的二进制字节码文件（class文件）通过I/O流的形式，读取进JVM内存中的方法区中
 *          然后通过一系列步骤,完成类加载.
 *          类加载需要通过I/O的形式实现,相比较于Java程序的执行来说,它的效率非常低
 *      2.既然类加载的效率不高,那么类加载是越多越好还是越少越好? 当然是更少的好
 *      2.既然类加载的效率不高,那么类加载是一股脑全部加载,还是用的时候再加载呢?
 *          Java对类加载的设计是"懒加载" 只有当程序的运行必须要类加载某个类时,迫不得已时
 *          才会类加载某个类
 *      4.在Java代码中,把必须要进行某个类,类加载的场景,称之为"类加载的时机"
 *          目前我们已知的类加载的时机:
 *              a.new对象
 *              b.启动main方法
 *          并且类加载在前,执行类加载完毕后,才继续执行上述"类加载时机"的代码.
 *      5.(最重要)某个类的类加载,在程序的某一次运行过程中,最多只会类加载一次,当然不类加载也完全可能.
 *
 * @since 15:59
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    // 启动main方法会触发Demo类的类加载,而且是先类加载完毕,再启动main方法
    public static void main(String[] args) {
        // 这里这个类必然要进行类加载
        Student s = new Student();

        // 这里会触发类加载吗? 不会,因为启动main方法已经类加载过一次了
        Demo d = new Demo();
    }
}
class Student{}
class A{}